﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows.Media.Animation;
using System.Windows;

namespace Gronia.WPF.Controls
{
    public partial class PageTransition : Control
    {
        protected Dictionary<PageTransitionType, Storyboard> InAnimations = new Dictionary<PageTransitionType, Storyboard>();
        protected Dictionary<PageTransitionType, Storyboard> OutAnimations = new Dictionary<PageTransitionType, Storyboard>();

        protected Storyboard SlideAndFadeIn;
        protected Storyboard SlideAndFadeOut;
        protected Storyboard FadeIn;
        protected Storyboard FadeOut;
        protected Storyboard SlideIn;
        protected Storyboard SlideOut;
        protected Storyboard GrowIn;
        protected Storyboard GrowOut;
        protected Storyboard GrowAndFadeIn;
        protected Storyboard GrowAndFadeOut;
        protected Storyboard FlipIn;
        protected Storyboard FlipOut;
        protected Storyboard FlipAndFadeIn;
        protected Storyboard FlipAndFadeOut;
        protected Storyboard SpinIn;
        protected Storyboard SpinOut;
        protected Storyboard SpinAndFadeIn;
        protected Storyboard SpinAndFadeOut;

        protected DoubleAnimation CreateFadeAnimation(bool isIn)
        {
            DoubleAnimation animation = new DoubleAnimation();
            if (isIn)
            {
                animation.Duration = new Duration(TimeSpan.FromSeconds(0.25));
                animation.From = 0;
                animation.To = 1;
            }
            else
            {
                animation.Duration = new Duration(TimeSpan.FromSeconds(0.5));
                animation.To = 0;
            }
            Storyboard.SetTargetProperty(animation, new PropertyPath("Opacity"));
            return animation;
        }

        protected void CreateAnimations()
        {
            FadeIn = new Storyboard();
            {
                DoubleAnimation animation1 = CreateFadeAnimation(true);
                FadeIn.Children.Add(animation1);
            }

            FadeOut = new Storyboard();
            {
                DoubleAnimation animation1 = CreateFadeAnimation(false);
                FadeOut.Children.Add(animation1);
            }

            SlideIn = new Storyboard();
            {
                ThicknessAnimation animation1 = new ThicknessAnimation();
                animation1.Duration = new Duration(TimeSpan.FromSeconds(0.75));
                animation1.From = new Thickness(500, 0, -500, 0);
                animation1.To = new Thickness(0);
                animation1.DecelerationRatio = 0.9;

                Storyboard.SetTargetProperty(animation1, new PropertyPath("Margin"));

                SlideIn.Children.Add(animation1);
            }

            SlideOut = new Storyboard();
            {
                ThicknessAnimation animation1 = new ThicknessAnimation();
                animation1.Duration = new Duration(TimeSpan.FromSeconds(0.5));
                animation1.To = new Thickness(-500, 0, 500, 0);
                animation1.AccelerationRatio = 0.9;

                Storyboard.SetTargetProperty(animation1, new PropertyPath("Margin"));

                SlideOut.Children.Add(animation1);
            }

            SlideAndFadeIn = new Storyboard();
            {
                ThicknessAnimation animation1 = new ThicknessAnimation();
                animation1.Duration = new Duration(TimeSpan.FromSeconds(0.75));
                animation1.From = new Thickness(500, 0, -500, 0);
                animation1.To = new Thickness(0);
                animation1.DecelerationRatio = 0.9;

                DoubleAnimation animation2 = CreateFadeAnimation(true);

                Storyboard.SetTargetProperty(animation1, new PropertyPath("Margin"));

                SlideAndFadeIn.Children.Add(animation1);
                SlideAndFadeIn.Children.Add(animation2);
            }

            SlideAndFadeOut = new Storyboard();
            {
                ThicknessAnimation animation1 = new ThicknessAnimation();
                animation1.Duration = new Duration(TimeSpan.FromSeconds(0.5));
                animation1.To = new Thickness(-500, 0, 500, 0);
                animation1.AccelerationRatio = 0.9;

                DoubleAnimation animation2 = CreateFadeAnimation(false);

                Storyboard.SetTargetProperty(animation1, new PropertyPath("Margin"));

                SlideAndFadeOut.Children.Add(animation1);
                SlideAndFadeOut.Children.Add(animation2);
            }

            GrowIn = new Storyboard();
            {
                DoubleAnimation animation1 = new DoubleAnimation();
                animation1.From = 0;
                animation1.To = 1;
                animation1.Duration = new Duration(TimeSpan.FromSeconds(0.75));
                animation1.DecelerationRatio = 0.9;

                DoubleAnimation animation2 = animation1.Clone();

                Storyboard.SetTargetProperty(animation1, new PropertyPath("(RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"));
                Storyboard.SetTargetProperty(animation2, new PropertyPath("(RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"));

                GrowIn.Children.Add(animation1);
                GrowIn.Children.Add(animation2);
            }

            GrowOut = new Storyboard();
            {
                DoubleAnimation animation1 = new DoubleAnimation();
                animation1.To = 0;
                animation1.Duration = new Duration(TimeSpan.FromSeconds(0.75));
                animation1.AccelerationRatio = 0.9;

                DoubleAnimation animation2 = animation1.Clone();

                Storyboard.SetTargetProperty(animation1, new PropertyPath("(RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"));
                Storyboard.SetTargetProperty(animation2, new PropertyPath("(RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"));

                GrowOut.Children.Add(animation1);
                GrowOut.Children.Add(animation2);
            }

            GrowAndFadeIn = new Storyboard();
            {
                DoubleAnimation animation1 = new DoubleAnimation();
                animation1.From = 0;
                animation1.To = 1;
                animation1.Duration = new Duration(TimeSpan.FromSeconds(0.75));
                animation1.DecelerationRatio = 0.9;

                DoubleAnimation animation2 = animation1.Clone();

                DoubleAnimation animation3 = CreateFadeAnimation(true);

                Storyboard.SetTargetProperty(animation1, new PropertyPath("(RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"));
                Storyboard.SetTargetProperty(animation2, new PropertyPath("(RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"));

                GrowAndFadeIn.Children.Add(animation1);
                GrowAndFadeIn.Children.Add(animation2);
                GrowAndFadeIn.Children.Add(animation3);
            }

            GrowAndFadeOut = new Storyboard();
            {
                DoubleAnimation animation1 = new DoubleAnimation();
                animation1.To = 0;
                animation1.Duration = new Duration(TimeSpan.FromSeconds(0.75));
                animation1.AccelerationRatio = 0.9;

                DoubleAnimation animation2 = animation1.Clone();

                DoubleAnimation animation3 = CreateFadeAnimation(false);

                Storyboard.SetTargetProperty(animation1, new PropertyPath("(RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"));
                Storyboard.SetTargetProperty(animation2, new PropertyPath("(RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"));

                GrowAndFadeOut.Children.Add(animation1);
                GrowAndFadeOut.Children.Add(animation2);
                GrowAndFadeOut.Children.Add(animation3);
            }

            FlipIn = new Storyboard();
            {
                DoubleAnimation animation1 = new DoubleAnimation();
                animation1.From = -100;
                animation1.To = 0;
                animation1.Duration = new Duration(TimeSpan.FromSeconds(0.75));
                animation1.DecelerationRatio = 0.9;

                DoubleAnimation animation2 = animation1.Clone();

                Storyboard.SetTargetProperty(animation1, new PropertyPath("(RenderTransform).(TransformGroup.Children)[1].(SkewTransform.AngleX)"));
                Storyboard.SetTargetProperty(animation2, new PropertyPath("(RenderTransform).(TransformGroup.Children)[1].(SkewTransform.AngleY)"));

                FlipIn.Children.Add(animation1);
                FlipIn.Children.Add(animation2);
            }

            FlipOut = new Storyboard();
            {
                DoubleAnimation animation1 = new DoubleAnimation();
                animation1.To = 100;
                animation1.Duration = new Duration(TimeSpan.FromSeconds(0.75));
                animation1.AccelerationRatio = 0.9;

                DoubleAnimation animation2 = animation1.Clone();

                Storyboard.SetTargetProperty(animation1, new PropertyPath("(RenderTransform).(TransformGroup.Children)[1].(SkewTransform.AngleX)"));
                Storyboard.SetTargetProperty(animation2, new PropertyPath("(RenderTransform).(TransformGroup.Children)[1].(SkewTransform.AngleY)"));

                FlipOut.Children.Add(animation1);
                FlipOut.Children.Add(animation2);
            }

            FlipAndFadeIn = new Storyboard();
            {
                DoubleAnimation animation1 = new DoubleAnimation();
                animation1.From = -100;
                animation1.To = 0;
                animation1.Duration = new Duration(TimeSpan.FromSeconds(0.75));
                animation1.DecelerationRatio = 0.9;

                DoubleAnimation animation2 = animation1.Clone();

                DoubleAnimation animation3 = CreateFadeAnimation(true);

                Storyboard.SetTargetProperty(animation1, new PropertyPath("(RenderTransform).(TransformGroup.Children)[1].(SkewTransform.AngleX)"));
                Storyboard.SetTargetProperty(animation2, new PropertyPath("(RenderTransform).(TransformGroup.Children)[1].(SkewTransform.AngleY)"));

                FlipAndFadeIn.Children.Add(animation1);
                FlipAndFadeIn.Children.Add(animation2);
                FlipAndFadeIn.Children.Add(animation3);
            }

            FlipAndFadeOut = new Storyboard();
            {
                DoubleAnimation animation1 = new DoubleAnimation();
                animation1.To = 100;
                animation1.Duration = new Duration(TimeSpan.FromSeconds(0.75));
                animation1.AccelerationRatio = 0.9;

                DoubleAnimation animation2 = animation1.Clone();

                DoubleAnimation animation3 = CreateFadeAnimation(false);

                Storyboard.SetTargetProperty(animation1, new PropertyPath("(RenderTransform).(TransformGroup.Children)[1].(SkewTransform.AngleX)"));
                Storyboard.SetTargetProperty(animation2, new PropertyPath("(RenderTransform).(TransformGroup.Children)[1].(SkewTransform.AngleY)"));

                FlipAndFadeOut.Children.Add(animation1);
                FlipAndFadeOut.Children.Add(animation2);
                FlipAndFadeOut.Children.Add(animation3);
            }

            SpinIn = new Storyboard();
            {
                DoubleAnimation animation1 = new DoubleAnimation();
                animation1.From = -360;
                animation1.To = 0;
                animation1.Duration = new Duration(TimeSpan.FromSeconds(0.75));
                animation1.DecelerationRatio = 0.9;

                DoubleAnimation animation2 = new DoubleAnimation();
                animation2.DecelerationRatio = 0.9;
                animation2.From = 0;
                animation2.To = 1;
                animation2.Duration = new Duration(TimeSpan.FromSeconds(0.75));

                DoubleAnimation animation3 = animation2.Clone();

                Storyboard.SetTargetProperty(animation1, new PropertyPath("(RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)"));
                Storyboard.SetTargetProperty(animation2, new PropertyPath("(RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"));
                Storyboard.SetTargetProperty(animation3, new PropertyPath("(RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"));

                SpinIn.Children.Add(animation1);
                SpinIn.Children.Add(animation2);
                SpinIn.Children.Add(animation3);
            }

            SpinOut = new Storyboard();
            {
                DoubleAnimation animation1 = new DoubleAnimation();
                animation1.To = 360;
                animation1.Duration = new Duration(TimeSpan.FromSeconds(0.75));
                animation1.AccelerationRatio = 0.9;

                DoubleAnimation animation2 = new DoubleAnimation();
                animation2.AccelerationRatio = 0.9;
                animation2.To = 0;
                animation2.Duration = new Duration(TimeSpan.FromSeconds(0.75));

                DoubleAnimation animation3 = animation2.Clone();

                Storyboard.SetTargetProperty(animation1, new PropertyPath("(RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)"));
                Storyboard.SetTargetProperty(animation2, new PropertyPath("(RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"));
                Storyboard.SetTargetProperty(animation3, new PropertyPath("(RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"));

                SpinOut.Children.Add(animation1);
                SpinOut.Children.Add(animation2);
                SpinOut.Children.Add(animation3);
            }

            SpinAndFadeIn = new Storyboard();
            {
                DoubleAnimation animation1 = new DoubleAnimation();
                animation1.From = -360;
                animation1.To = 0;
                animation1.Duration = new Duration(TimeSpan.FromSeconds(0.75));
                animation1.DecelerationRatio = 0.9;

                DoubleAnimation animation2 = new DoubleAnimation();
                animation2.DecelerationRatio = 0.9;
                animation2.From = 0;
                animation2.To = 1;
                animation2.Duration = new Duration(TimeSpan.FromSeconds(0.75));

                DoubleAnimation animation3 = animation2.Clone();

                DoubleAnimation animation4 = CreateFadeAnimation(true);

                Storyboard.SetTargetProperty(animation1, new PropertyPath("(RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)"));
                Storyboard.SetTargetProperty(animation2, new PropertyPath("(RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"));
                Storyboard.SetTargetProperty(animation3, new PropertyPath("(RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"));

                SpinAndFadeIn.Children.Add(animation1);
                SpinAndFadeIn.Children.Add(animation2);
                SpinAndFadeIn.Children.Add(animation3);
                SpinAndFadeIn.Children.Add(animation4);
            }

            SpinAndFadeOut = new Storyboard();
            {
                DoubleAnimation animation1 = new DoubleAnimation();
                animation1.To = 360;
                animation1.Duration = new Duration(TimeSpan.FromSeconds(0.75));
                animation1.AccelerationRatio = 0.9;

                DoubleAnimation animation2 = new DoubleAnimation();
                animation2.AccelerationRatio = 0.9;
                animation2.To = 0;
                animation2.Duration = new Duration(TimeSpan.FromSeconds(0.75));

                DoubleAnimation animation3 = animation2.Clone();

                DoubleAnimation animation4 = CreateFadeAnimation(false);

                Storyboard.SetTargetProperty(animation1, new PropertyPath("(RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)"));
                Storyboard.SetTargetProperty(animation2, new PropertyPath("(RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"));
                Storyboard.SetTargetProperty(animation3, new PropertyPath("(RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"));

                SpinAndFadeOut.Children.Add(animation1);
                SpinAndFadeOut.Children.Add(animation2);
                SpinAndFadeOut.Children.Add(animation3);
                SpinAndFadeOut.Children.Add(animation4);
            }

            AnimationsLoaded();
        }

        protected void AnimationsLoaded()
        {
            InAnimations.Add(PageTransitionType.Fade, FadeIn);
            InAnimations.Add(PageTransitionType.Flip, FlipIn);
            InAnimations.Add(PageTransitionType.FlipAndFade, FlipAndFadeIn);
            InAnimations.Add(PageTransitionType.Grow, GrowIn);
            InAnimations.Add(PageTransitionType.GrowAndFade, GrowAndFadeIn);
            InAnimations.Add(PageTransitionType.Slide, SlideIn);
            InAnimations.Add(PageTransitionType.SlideAndFade, SlideAndFadeIn);
            InAnimations.Add(PageTransitionType.Spin, SpinIn);
            InAnimations.Add(PageTransitionType.SpinAndFade, SpinAndFadeIn);

            OutAnimations.Add(PageTransitionType.Fade, FadeOut);
            OutAnimations.Add(PageTransitionType.Flip, FlipOut);
            OutAnimations.Add(PageTransitionType.FlipAndFade, FlipAndFadeOut);
            OutAnimations.Add(PageTransitionType.Grow, GrowOut);
            OutAnimations.Add(PageTransitionType.GrowAndFade, GrowAndFadeOut);
            OutAnimations.Add(PageTransitionType.Slide, SlideOut);
            OutAnimations.Add(PageTransitionType.SlideAndFade, SlideAndFadeOut);
            OutAnimations.Add(PageTransitionType.Spin, SpinOut);
            OutAnimations.Add(PageTransitionType.SpinAndFade, SpinAndFadeOut);
        }

    }
}